package com.anorak.betsy.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.anorak.betsy.entity.Music;
import com.anorak.betsy.entity.Song;
import com.anorak.betsy.entity.Verify;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author anorak
 */
public class HiFiNiUtil {


    private final static String BASE_PATH = "/Users/anorak/Documents/JavaProject/standalone/Akby/musicflit/src/main/resources";

    private final static String EMAIL = "2940397985@qq.com";

    private final static String PASSWORD = "e10adc3949ba59abbe56e057f20f883e";

    private final static String HiFiNi_LANZOU_URL = "https://hifini.lanzou";


    private final static String HiFiNi_URL = "https://www.hifini.com/";

    private final static String CAPTCHA_URL = "https://www.hifini.com/captcha_get.htm";

    private final static String CHECK_URL = "https://www.hifini.com/captcha_check.htm";

    private final static String LOGIN_URL = "https://www.hifini.com/user-login.htm";

    private final static String SIGN_URL = "https://www.hifini.com/sg_sign.htm";

    private final static String SEARCH_URL_PREFIX = "https://www.hifini.com/search-";

    private final static String SEARCH_URL_SUFFIX = "-1.htm";

    public static Verify getCaptcha() {
        Verify verify = null;
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("captchaType", "blockPuzzle");
        jsonObject.set("clientUid", "slider-7d37b24e-806d-4d62-8913-db84f2fe0b86");
        jsonObject.set("ts", System.currentTimeMillis());
        Map<String, String> heads = new HashMap<>();
        heads.put("Content-Type", "application/json;charset=UTF-8");
        HttpResponse response = HttpRequest.post(CAPTCHA_URL).headerMap(heads, false).body(String.valueOf(jsonObject)).timeout(5 * 60 * 1000).execute();
        JSONObject json = new JSONObject(response.body().trim());
        verify = json.getByPath("repData", Verify.class);
        return verify;
    }

    public static boolean checkCaptcha(Verify verify, Integer move) throws Exception {
        String content = "{\"x\":" + move + ",\"y\":5}";
        String aes = AesUtil.aesEncrypt(content, verify.getSecretKey());
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("captchaType", "blockPuzzle");
        jsonObject.set("pointJson", aes);
        jsonObject.set("token", verify.getToken());
        jsonObject.set("clientUid", "slider-7d37b24e-806d-4d62-8913-db84f2fe0b86");
        jsonObject.set("ts", System.currentTimeMillis());
        String bbsSid = cookie();
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        MediaType mediaType = MediaType.parse("application/json;charset=UTF-8");
        RequestBody body = RequestBody.create(mediaType, JSONUtil.toJsonStr(jsonObject));
        Request request = new Request.Builder().url(CHECK_URL).method("POST", body).addHeader("authority", "www.hifini.com").addHeader("Cookie", "bbs_sid=" + bbsSid + "; Hm_lpvt_4ab5ca5f7f036f4a4747f1836fffe6f2=" + System.currentTimeMillis()).addHeader("content-type", "application/json;charset=UTF-8").addHeader("Host", "www.hifini.com").build();
        Response response = client.newCall(request).execute();
        if (response.body() != null) {
            JSONObject json = new JSONObject(response.body().string().trim());
            String repCode = json.getByPath("repCode", String.class);
            if ("0000".equalsIgnoreCase(repCode)) {
                verify.setPointJson(aes);
                verify.setBbsSid(bbsSid);
                return true;
            }
            return false;
        }
        return false;
    }

    public static String cookie() {
        HttpResponse response = HttpRequest.get(HiFiNi_URL).timeout(5 * 60 * 1000).execute();
        if (response.getStatus() == 200) {
            return response.getCookie("bbs_sid").getValue();
        }
        return "";
    }

    public static boolean loginAccount(Verify verify) throws IOException {
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8");
        RequestBody body = RequestBody.create(mediaType, "email=" + EMAIL + "&password=" + PASSWORD + "&xn_token=" + verify.getToken() + "&xn_pointJson=" + verify.getPointJson());
        Request request = new Request.Builder().url(LOGIN_URL).method("POST", body).addHeader("authority", "www.hifini.com").addHeader("x-requested-with", "XMLHttpRequest").addHeader("Cookie", "bbs_sid=" + verify.getBbsSid() + "; Hm_lpvt_4ab5ca5f7f036f4a4747f1836fffe6f2=" + System.currentTimeMillis()).addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)").addHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8").addHeader("Accept", "*/*").addHeader("Host", "www.hifini.com").addHeader("Connection", "keep-alive").build();
        Response response = client.newCall(request).execute();
        String jsonStr = response.body().string().trim();
        JSONObject json = new JSONObject(jsonStr);
        String code = json.getByPath("code", String.class);
        if ("0".equalsIgnoreCase(code)) {
            String setCookie = response.header("Set-Cookie");
            String[] strings = setCookie.split(";");
            for (String string : strings) {
                if (string.contains("bbs_token=")) {
                    verify.setBbsToken(string.trim().replace("bbs_token=", ""));
                }
            }
            return true;
        }
        return false;
    }

    public static void signAccount(Verify verify) throws IOException {
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        MediaType mediaType = MediaType.parse("text/plain");
        RequestBody body = RequestBody.create(mediaType, "");
        Request request = new Request.Builder().url(SIGN_URL).method("POST", body).addHeader("authority", "www.hifini.com").addHeader("pragma", "no-cache").addHeader("x-requested-with", "XMLHttpRequest").addHeader("Cookie", "bbs_sid=" + verify.getBbsSid() + "; bbs_token=" + verify.getBbsToken() + "; Hm_lpvt_4ab5ca5f7f036f4a4747f1836fffe6f2=" + System.currentTimeMillis()).addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)").addHeader("Accept", "*/*").addHeader("Host", "www.hifini.com").addHeader("Connection", "keep-alive").build();
        Response response = client.newCall(request).execute();
    }

    public static void searchMusic(Verify verify, Music music) throws IOException {
        if (!music.getSongList().isEmpty()) {
            for (Song song : music.getSongList()) {
                String searchTag = SearchUtil.searchName(TagConvertUtil.tagConvert(song.getSearchTag()));
                buildMusicInfo(searchTag, song, verify);
            }
        }
    }

    private static void buildMusicInfo(String searchTag, Song song, Verify verify) throws IOException {
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder().url(SEARCH_URL_PREFIX + searchTag + SEARCH_URL_SUFFIX).method("GET", null).addHeader("authority", "www.hifini.com").addHeader("pragma", "no-cache").addHeader("sec-fetch-user", "?1").addHeader("upgrade-insecure-requests", "1").addHeader("Cookie", "bbs_sid=" + verify.getBbsSid() + "; bbs_token=" + verify.getBbsToken() + "; Hm_lpvt_4ab5ca5f7f036f4a4747f1836fffe6f2=" + System.currentTimeMillis()).addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)").addHeader("Accept", "*/*").addHeader("Host", "www.hifini.com").addHeader("Connection", "keep-alive").build();
        Response response = client.newCall(request).execute();
        String jsonStr = response.body().string().trim();
        if (StringUtils.isNotEmpty(jsonStr)) {
            Document document = Jsoup.parse(jsonStr);
            Element element = document.getElementsByClass("media thread tap  ").first();
            if (element != null) {
                song.setHref(HiFiNi_URL + element.attributes().get("data-href"));
                buildDownloadInfo(song, verify);
            }
        }
    }

    private static void buildDownloadInfo(Song song, Verify verify) throws IOException {
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder().url(song.getHref()).method("GET", null).addHeader("authority", "www.hifini.com").addHeader("pragma", "no-cache").addHeader("sec-fetch-user", "?1").addHeader("upgrade-insecure-requests", "1").addHeader("Cookie", "bbs_sid=" + verify.getBbsSid() + "; bbs_token=" + verify.getBbsToken() + "; Hm_lpvt_4ab5ca5f7f036f4a4747f1836fffe6f2=" + System.currentTimeMillis()).addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)").addHeader("Accept", "*/*").addHeader("Host", "www.hifini.com").addHeader("Connection", "keep-alive").build();
        Response response = client.newCall(request).execute();
        String jsonStr = response.body().string().trim();
        if (StringUtils.isNotEmpty(jsonStr)) {
            if (jsonStr.contains(HiFiNi_LANZOU_URL)) {
                Document document = Jsoup.parse(jsonStr);
                List<String> ignoreList = new ArrayList<>();
                Elements styles = document.getElementById("body").getElementsByClass("container").first().select("style");
                for (Element style : styles.subList(0, 2)) {
                    String text = style.childNode(0).attributes().get("data");
                    if (text.contains("{display:none !important;}")) {
                        String[] strings = text.split("display:inline !important;}");
                        String test = strings[1].replace("{display:none !important;}", "").replace(",", "");
                        for (String s : test.split("\\.")) {
                            if (StringUtils.isNotEmpty(s)) {
                                ignoreList.add(s);
                            }
                        }
                    }
                }
                Elements elements = document.select("a[href][target]");
                for (Element element : elements) {
                    String url = element.attributes().get("href");
                    if (url.contains(HiFiNi_LANZOU_URL)) {
                        song.setLanZouUrl(url);
                        StringBuffer stringBuffer = new StringBuffer();
                        Elements spans = ((Element) element.parentNode()).getElementsByTag("span");
                        for (Element span : spans) {
                            String classStr = span.attributes().get("class");
                            if (!ignoreList.contains(classStr)) {
                                stringBuffer.append(span.text());
                            }
                        }
                        song.setLanZouPassWord(stringBuffer.toString());
                    }
                }
            }
        }
    }

    public static void downloadMusic(Music music) throws IOException {
        if (!music.getSongList().isEmpty()) {
            for (Song song : music.getSongList()) {
                if (StringUtils.isNotEmpty(song.getLanZouUrl()) && StringUtils.isNotEmpty(song.getLanZouPassWord())) {
                    OkHttpClient client = new OkHttpClient().newBuilder().build();
                    Request request = new Request.Builder().url("https://lz.qaiu.top/json/parser?url=" + song.getLanZouUrl() + "&pwd=" + song.getLanZouPassWord()).method("GET", null).addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)").addHeader("Accept", "*/*").addHeader("Host", "lz.qaiu.top").addHeader("Connection", "keep-alive").build();
                    Response response = client.newCall(request).execute();
                    String jsonStr = response.body().string().trim();
                    JSONObject json = new JSONObject(jsonStr);
                    String zipPath = BASE_PATH + "/" + music.getListId() + "/zip/" + song.getName() + ".zip";
                    song.setZipPath(zipPath);
                    HttpUtil.downloadFile(json.get("data").toString(), zipPath);
                    String temp = BASE_PATH + "/" + music.getListId() + "/zip/" + song.getName() + "/";
                    ZipUtil.unzip(zipPath, temp, Charset.forName("gbk"));
                    List<File> fileList = FileUtil.loopFiles(temp);
                    String mp3Path = BASE_PATH + "/" + music.getListId() + "/mp3/";
                    String flacPath = BASE_PATH + "/" + music.getListId() + "/flac/";
                    for (File file : fileList) {
                        if (file.isFile()) {
                            if (file.getName().contains(".mp3")) {
                                song.setMp3path(mp3Path + file.getName());
                                FileUtil.move(file, new File(mp3Path + file.getName()), true);
                            } else if (file.getName().contains(".flac")) {
                                song.setFlacPath(flacPath + file.getName());
                                FileUtil.move(file, new File(flacPath + file.getName()), true);
                            }
                        }
                    }
                    DeleteFileUtil.deleteDirectory(temp);
                }
            }
        }
    }

    public static void logMusic(Music music) {
        String mp3Path = BASE_PATH + "/" + music.getListId() + "/mp3/";
        String flacPath = BASE_PATH + "/" + music.getListId() + "/flac/";
        String zipPath = BASE_PATH + "/" + music.getListId() + "/zip/";
        StringBuilder mp3Buffer = new StringBuilder();
        StringBuilder flacBuffer = new StringBuilder();
        StringBuilder zipBuffer = new StringBuilder();
        mp3Buffer.append("下载的歌曲如下 : ").append("\n");
        flacBuffer.append("下载的歌曲如下 : ").append("\n");
        zipBuffer.append("下载的歌曲如下 : ").append("\n");
        for (Song song : music.getSongList()) {
            if (StringUtils.isNotEmpty(song.getMp3path())) {
                mp3Buffer.append(song.getAbsName()).append("\n");
            }
            if (StringUtils.isNotEmpty(song.getFlacPath())) {
                flacBuffer.append(song.getAbsName()).append("\n");
            }
            if (StringUtils.isNotEmpty(song.getZipPath())) {
                zipBuffer.append(song.getAbsName()).append("\n");
            }
        }
        mp3Buffer.append("----------------------------------").append("\n");
        flacBuffer.append("---------------------------------").append("\n");
        zipBuffer.append("---------------------------------").append("\n");
        mp3Buffer.append("尚未下载的歌曲如下 : ").append("\n");
        flacBuffer.append("尚未下载的歌曲如下 : ").append("\n");
        zipBuffer.append("尚未下载的歌曲如下 : ").append("\n");
        for (Song song : music.getSongList()) {
            if (!StringUtils.isNotEmpty(song.getMp3path())) {
                mp3Buffer.append(song.getAbsName()).append("\n");
            }
            if (!StringUtils.isNotEmpty(song.getFlacPath())) {
                flacBuffer.append(song.getAbsName()).append("\n");
            }
            if (!StringUtils.isNotEmpty(song.getZipPath())) {
                zipBuffer.append(song.getAbsName()).append("\n");
            }
        }
        try {
            FileUtil.writeUtf8String(mp3Buffer.toString(), mp3Path + "/MP3.txt");
            FileUtil.writeUtf8String(flacBuffer.toString(), flacPath + "/FLAC.txt");
            FileUtil.writeUtf8String(zipBuffer.toString(), zipPath + "/ZIP.txt");
        } catch (Exception ignored) {
        }
    }

}
